//
//  ADScanViewController.swift
//  ADKit
//
//  Created by Adoma on 2020/11/13.
//

import UIKit
import AVFoundation

open class ADScanViewController: UIViewController {
    
    public typealias ScanResult = Result<String,NSError>
    public var callBack: ((ScanResult) -> Void)?
    var preLayer: AVCaptureVideoPreviewLayer?
    var session: AVCaptureSession?
    
    var captureView = UIView()
    
    override open func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        initSession()
    }
    
    func setupUI() {
        
        view.backgroundColor = .white
        
        view.addSubview(captureView)
        captureView.snp.makeConstraints { (make) in
            make.top.left.right.bottom.equalToSuperview()
        }
        
        let scanMask = UIImageView.init(image: UIImage(name: "scaner_back", bundle: .for(name: "ADKit")))
        view.addSubview(scanMask)
        scanMask.snp.makeConstraints { (make) in
            make.top.left.right.bottom.equalTo(captureView)
        }
        
    }
    
    override public func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if session?.isRunning == false {
            session?.startRunning()
        }
    }
    
    public override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
    }
    
    deinit {
        preLayer?.removeFromSuperlayer()
        session?.stopRunning()
    }
    
    @objc func getFromAlbum() {
        let vc = UIImagePickerController.init()
        vc.sourceType = .photoLibrary
        vc.delegate = self
        vc.modalPresentationStyle = .fullScreen
        session?.stopRunning()
        
       try? ADRouter.routeWith(target: vc, param: [ADRouterKey.isPresentTransAction: true])
    }
    
    func initSession() {
        
        guard let device = AVCaptureDevice.default(for: .video) else {
            callBack?(ScanResult.failure(NSError.init(domain: "初始化失败", code: 0)))
            return
        }
        guard let input = try? AVCaptureDeviceInput.init(device: device) else {
            callBack?(ScanResult.failure(NSError.init(domain: "获取输入失败", code: 0)))
            return
        }
        
        view.layoutIfNeeded()
        
        let output = AVCaptureMetadataOutput.init()
        output.rectOfInterest = view.bounds
        output.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
        
        session = .init()
        session?.sessionPreset = .hd1920x1080
        session?.addOutput(output)
        session?.addInput(input)
        
        //识别类型需在addOutput之后设置
        output.metadataObjectTypes = [.qr, .code128, .code39, .code39Mod43, .ean13, .ean8, .code93]
        preLayer = AVCaptureVideoPreviewLayer.init(session: session!)
        preLayer?.videoGravity = .resizeAspectFill
        preLayer?.frame = captureView.bounds
        captureView.layer.insertSublayer(preLayer!, at: 0)
        session?.startRunning()
    }
    
    open func dealResult(_ result: String) {
        session?.stopRunning()
        callBack?(ScanResult.success(result))
        ADLogger(adkit: Self.self)
            .debug(result)
    }
    
}

extension ADScanViewController: AVCaptureMetadataOutputObjectsDelegate {
    public func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        guard let result = (metadataObjects.first as? AVMetadataMachineReadableCodeObject)?.stringValue  else {
            return
        }
        dealResult(result)
    }
}

extension ADScanViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        if session?.isRunning == false {
            session?.startRunning()
        }
        picker.dismiss(animated: true, completion: nil)
    }
    
    public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true, completion: nil)
        
        if let image = info[.originalImage] as? UIImage {
            dealImage(image)
        } else {
            ADToast.show(msg: "无效图片")
            session?.startRunning()
        }
    }
    
    func dealImage(_ image: UIImage) {
        let detetor = CIDetector.init(ofType: CIDetectorTypeQRCode, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh])
        if let features = detetor?.features(in: CIImage.init(image: image)!) {
            for item in features {
                if let result = (item as? CIQRCodeFeature)?.messageString {
                    dealResult(result)
                    return
                }
            }
            ADToast.show(msg: "无效图片")
            session?.startRunning()
        } else {
            ADToast.show(msg: "无效图片")
            session?.startRunning()
        }
    }
}
